﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Framework.Utils
{
    public static class FileUtils
    {
        /// <summary>
        /// 打开文件夹
        /// </summary>
        public static void OpenFolder(string path)
        {
            path = Path.GetFullPath(path);
            System.Diagnostics.Process.Start("explorer", path);
        }


        // 绝对路径转相对路径
        public static string RelativePath(string absolutePath, string relativeTo)
        {
            //from - www.cnphp6.com
            string[] absoluteDirectories = absolutePath.Split('\\');
            string[] relativeDirectories = relativeTo.Split('\\');

            //Get the shortest of the two paths
            int length = (absoluteDirectories.Length < relativeDirectories.Length) ? absoluteDirectories.Length : relativeDirectories.Length;

            //Use to determine where in the loop we exited
            int lastCommonRoot = -1;
            int index;

            //Find common root
            for (index = 0; index < length; index++)
            {
                if (absoluteDirectories[index] == relativeDirectories[index])
                {
                    lastCommonRoot = index;
                }
                else
                {
                    break;
                }
            }

            //If we didn't find a common prefix then throw
            if (lastCommonRoot == -1)
            {
                throw new ArgumentException("Paths do not have a common base");
            }

            //Build up the relative path
            StringBuilder relativePath = new StringBuilder();

            //Add on the ..
            for (index = lastCommonRoot + 1; index < absoluteDirectories.Length; index++)
            {
                if (absoluteDirectories[index].Length > 0)
                {
                    relativePath.Append("..\\");
                }
            }

            //Add on the folders
            for (index = lastCommonRoot + 1; index < relativeDirectories.Length - 1; index++)
            {
                relativePath.Append(relativeDirectories[index] + "\\");
            }
            relativePath.Append(relativeDirectories[relativeDirectories.Length - 1]);
            return relativePath.ToString();
        }

        /// <summary>
        /// 返回绝对路径, 如果是则直接返回.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        [Obsolete("请使用源生方法 Path.GetFullPath")]
        public static string GetAbsolutePath(string path)
        {
            // if (Path.IsPathRooted(path)) { return path; }
            return Path.GetFullPath(path);
        }


        /// <summary>
        /// 从文件路径中筛选出文件名
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        [Obsolete("请使用源生方法 Path.GetFileName()")]
        public static string GetFileName(string filePath)
        {
            filePath = filePath.Replace("\\", "/");
            int lid = filePath.LastIndexOf("/");
            if (lid < 0) { return filePath; }
            return filePath.Substring(lid + 1);
        }

        /// <summary>
        /// 从文件中筛选出路径
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        [Obsolete("请使用源生方法 Path.GetDirectoryName()")]
        public static string GetFilePath(string filePath)
        {
            filePath = filePath.Replace("\\", "/");
            int lid = filePath.LastIndexOf("/");
            if (lid < 0) { return filePath; }
            return filePath.Substring(0, lid);
        }


        //读取文本文件
        public static string LoadFile(string filePath, string charsetName)
        {
            try
            {
                //读取文件
                FileStream fileStream = new FileStream(filePath, FileMode.Open);
                fileStream.Seek(0, SeekOrigin.Begin);
                //获取大小
                long bufSize = fileStream.Length;


                //读取出数据
                long readsize = 0;
                byte[] buffer = LoadStream(fileStream, bufSize, (int)(bufSize * 0.5f), out readsize);


                //关闭文件
                fileStream.Close();

                //判断处理
                if (buffer == null) { return null; }

                //解析字符串
                Encoding encoding = Encoding.GetEncoding(charsetName);
                string retStr = encoding.GetString(buffer);
                return retStr;
            }
            catch (IOException ex)
            {
                Console.WriteLine("file path:" + (new FileInfo(filePath).FullName));
                Console.WriteLine(ex.ToString());
            }

            return null;
        }

        //从数据流读取数据
        private static byte[] LoadStream(Stream stream, long maxSize, int oneSize, out long outsize)
        {
            //生成总缓存大小
            byte[] buffer = new byte[maxSize];
            int totalSize = 0;
            //生成一次读取的临时缓存
            byte[] tempBuf = new byte[oneSize];

            while (true)
            {
                int size = stream.Read(tempBuf, 0, oneSize);
                if (size <= 0) { break; }

                //复制到数据中
                Buffer.BlockCopy(tempBuf, 0, buffer, totalSize, size);
                totalSize += size;
                if (totalSize > maxSize) { outsize = 0; return null; }
            }
            outsize = totalSize;
            return buffer;
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="data"></param>
        /// <param name="charsetName"></param>
        /// <param name="append"></param>
        /// <returns></returns>
        public static bool SaveFile(string path, string data, string charsetName, bool append = false)
        {
            try
            {
                // create path
                var dirinfo = new DirectoryInfo(Path.GetDirectoryName(path));
                if (!dirinfo.Exists)
                {
                    dirinfo.Create();
                }

                //解析字符串
                //Encoding encoding = Encoding.GetEncoding(charsetName);
                //byte[] buffer = encoding.GetBytes(data);
                
                //FileMode fileModel = (append) ? FileMode.Append : FileMode.OpenOrCreate;
                //FileStream fileStream = new FileStream(path, fileModel);

                ////写入数据
                //fileStream.Write(buffer, 0, buffer.Length);

                //fileStream.Close();

                var sw = new StreamWriter(path, append);
                sw.Write(data);
                sw.Close();


                //StreamWriter sw = new StreamWriter(path, append);

                //sw.Close();
                return true;
            }
            catch (IOException ex)
            {
                Console.WriteLine(ex.ToString());
            }

            return false;
        }
  
        public delegate bool DActionFolder(FileSystemInfo info);

        public static int ActionFolder(string path, string searchPattern, DActionFolder dfunc)
        {
            // 判断路径
            if (File.Exists(path))
            {
                return (dfunc(new FileInfo(path))) ? 1 : 0;
            }
            else if (Directory.Exists(path))
            {
                var dirinfo = new DirectoryInfo(path);
                return ActionFolderR(dirinfo, searchPattern, dfunc, 0);
            }
            return 0;
        }

        private static int ActionFolderR(DirectoryInfo dirinfo, string searchPattern, DActionFolder dfunc, int depth)
        {
            if (!dirinfo.Exists)
            {
                return 0;
            }
            int totalCount = 0;

            // 遍历文件
            var filelist = dirinfo.GetFiles(searchPattern);
            foreach (var fileInfo in filelist)
            {
                if (!dfunc(fileInfo))
                {
                    break;
                }
                totalCount++;
            }

            // 遍历文件夹
            var dirlist = dirinfo.GetDirectories();
            foreach (var difinfo_ in dirlist)
            {
                if (!dfunc(difinfo_))
                {
                    continue;
                }
                // action
                totalCount += ActionFolderR(difinfo_, searchPattern, dfunc, depth+1);
            }
            return totalCount;
        }
    }
}
